#include <stdio.h>

/*des.c*/
#include <math.h>
#include <stdlib.h>
#include <string.h>

//#include "bit.h"
#include "encrypt.h"

/*定义一个密钥置换的映射*/
static const int DesTransform[56] =
{
    57,49,41,33,25,17,9,1,58,50,42,34,26,18,
    10,2,59,51,43,35,27,19,11,3,60,52,44,36,
    63,55,47,39,31,23,15,7,62,54,46,38,30,22,
    14,6,61,53,45,37,29,21,13,5,28,20,12,4
};
/*定义用于计算子密钥的旋转次数*/
static const int DesRotations[16] =
{
    1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
/*定义用于子密钥置换选择的映射*/
static const int DesPermuted[48] =
{
    14,17,11,24,1,5,3,28,15,6,21,10,
    23,19,12,4,26,8,16,7,27,20,13,2,
    41,52,31,37,47,55,30,40,51,45,33,48,
    44,49,39,56,34,53,46,42,50,36,29,32
};
/*定义用于数据块初始化转换的映射*/
static const int DesInitial[64] =
{
    58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,
    62,54,46,38,30,22,14,6,64,56,48,40,32,24,16,8,
    57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,
    61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7
};
/*定义用于数据块扩展转换的映射*/
static const int DesExpansion[48] =
{
    32,1,2,3,4,5,4,5,6,7,8,9,
    8,9,10,11,12,13,12,13,14,15,16,17,
    16,17,18,19,20,21,22,23,24,25,
    24,25,26,27,28,29,28,29,30,31,32,1
};
/*定义用于数据块中S盒转换的S盒表*/
static const int DesSbox[8][4][16] =
{
    {
        {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},
        {0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},
        {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},
        {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13},
    },
    {
        {15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},
        {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},
        {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},
        {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9},
    },
    {
        {10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},
        {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},
        {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},
        {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12},
    },
    {
        {7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},
        {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},
        {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},
        {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14},
    },
    {
        {2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},
        {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},
        {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},
        {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3},
    },
    {
        {12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},
        {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},
        {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},
        {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13},
    },
    {
        {4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},
        {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},
        {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},
        {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12},
    },
    {
        {13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},
        {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},
        {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},
        {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11},
    }
};
/*定义用于数据块转换的P盒映射表*/
static const int DesPbox[32] =
{

};
/*定义用于数据块最终转换的映射*/
static const int DesFinal[64] =
{

};

/*定义一个枚举类型，用于选择是加密或是解密数据*/
typedef enum DesEorD_ {encipher,decipher} DesEorD;

/*permute函数  用于转换、改变位序列*/
static void permute(unsigned char *bits, const int *mapping, int n)
{
    unsigned char *temp[8];
    int i;

    /*使用n位映射映射缓冲区*/
    memset(temp, 0, (int)ceil(n/8));

    for(i=0; i<n; i++)
        bit_set(temp, i, bit_get(bits,mapping[i]-1));

    memcpy(bits, temp, (int)ceil(n/8));
    return;
}

/*des_main函数  加密或解密数据的计算函数*/
static int des_main(const unsigned char *source, unsigned char *target, const char *key, DesEorD direction)
{
    static unsigned char subkeys[16][7];
    unsigned char temp[8],
                  lkey[4],
                  rkey[4],
                  lblk[6],
                  rblk[6],
                  fblk[6],
                  xblk[6],
                  sblk;
    int row,col,i,j,k,p;

    /*如果key等于NULL，重用上次调用时计算出来的子密钥，否则计算子密钥*/
    if(key != NULL)
    {
        /*创建一个key的副本*/
        memcpy(temp,key,8);

        /*将key转换并压缩至56位*/
        permute(temp,DesTransform,56);

        /*将key分为两个28位的组*/
        memset(lkey,0,4);
        memset(rkey,0,4);

        for(j=0; j<28; j++)
            bit_set(lkey, j, bit_get(temp,j));

        for(j=0; j<28; j++)
            bit_set(rkey, j, bit_get(temp,j+28));

        /*计算每一轮的子密钥*/
        for(i=0; i<16; i++)
        {
            /*根据定义好的位数对每一块进行旋转*/
            bit_rot_left(lkey,28,DesRotations[i]);
            bit_rot_left(rkey,28,DesRotations[i]);

            /*重新合并两个块*/
            for(j=0; j<28; j++)
                bit_set(subkeys[i],j,bit_get(lkey,j));

            for(j=0; j<28; j++)
                bit_set(subkeys[i],j+28,bit_get(rkey,j));

            /*对子密钥做转换选择并压缩至48位*/
            permute(subkeys[i],DesPermuted,48);
        }
    }
    /*创建source参数的副本*/
    memcpy(temp, source, 8);

    /*初始转换数据块*/
    permute(temp, DesInitial, 64);

    /*将源数据块分为大小为32位的左右两个数据块*/
    memcpy(lblk, &temp[0], 4);
    memcpy(rblk, &temp[4], 4);

    /*加密或解密源数据*/
    for(i=0; i<16; i++)
    {
        /*开始f缓冲冲的计算*/
        memcpy(fblk,rblk,4);

        /*置换、扩展右数据块的拷贝，使其达到48位*/
        permute(fblk, DesExpansion, 48);

        /*根据direction的值来应用适当的子密钥*/
        if(direction == encipher)
        {
            /*加密数据，子密钥组以递增的顺序应用*/
            bit_xor(fblk, subkeys[i], xblk, 48);
            memcpy(fblk, xblk, 6);
        }
        else
        {
            /*解密数据，子密钥组以递减的顺序应用*/
            bit_xor(fblk, subkeys[15-i], xblk, 48);
            meycpy(fblk, xblk, 6);
        }

        /*执行S盒替换*/
        p=0;
        for(j=0; j<8; j++)
        {
            /*计算出S盒表中的行号和列号*/
            row = (bit_get(fblk,(j*6)+0)*2) + (bit_get(fblk,(j*6)+5)*1);
            col = (bit_get(fblk,(j*6)+1)*8) + (bit_get(fblk,(j*6)+2)*4) +
                  (bit_get(fblk,(j*6)+3)*2) + (bit_get(fblk,(j*6)+4)*1);
            /*为当前的6位数据块做S盒替换*/
            sblk = (unsigned char)DesSbox[j][row][col];
            for (k=4; k<8; k++)
            {
                bit_set(fblk,p,bit_get(&sblk,k));
                p++;
            }
        }

        /*为f缓冲区执行P盒替换*/
        permute(fblk, DesPbox, 32);

        /*计算左数据块与f缓冲区的异或值*/
        bit_xor(lblk, fblk, xblk, 32);

        /*设置本轮的左数据块*/
        memcpy(lblk, rblk, 4);
        /*设置本轮的右数据块*/
        memcpy(rblk, xblk, 4);
    }

    /*将目标正文设置为重新连接的左右两个数据块*/
    memcpy(&target[0], rblk, 4);
    memcpy(&target[4], lblk, 4);

    /*执行最终置换*/
    permute(target, DesFinal, 64);

    return 0;
}

/*des_encipher DES加密数据*/
void des_encipher(const unsigned char *plaintext, unsigned char *ciphertext, const unsigned char *key)
{
    des_main(plaintext, ciphertext, key, encipher);
    return;
}

/*des_decipher DES解密数据*/
void des_decipher(const unsigned char *ciphertext, unsigned char *plaintext, const unsigned char *key)
{
    des_main(ciphertext, plaintext, key, decipher);
    return;
}
